package ar.edu.unq.leezsi.utils;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.Properties;

import ar.edu.unq.leezsi.exception.CowebRuntimeException;

public class ClassWrapper<T> {

	final private Class<T> target;

	public ClassWrapper(final Class<T> clazz) {
		this.target = clazz;
	}

	@SuppressWarnings("unchecked")
	public ClassWrapper(final String className) {
		try {
			this.target = (Class<T>) Class.forName(className);
		} catch (ClassNotFoundException e) {
			throw new CowebRuntimeException(
					"Class " + className + " not Found", e);
		}
	}

	public Properties getProperties() {
		Properties ret = new Properties();
		try {
			ret.load(this.getResourceAsStream(this.simpleName()));
		} catch (IOException e) {
			throw new CowebRuntimeException(e);
		}
		return ret;
	}

	public URL getResource(String resource) {
		return this.target.getResource(resource);
	}

	public InputStream getResourceAsStream(String name) {
		return this.target.getResourceAsStream(name);
	}

	public String getResourceAsString(String resource) {
		InputStream resourceAsStream = this.getResourceAsStream(resource);
		try {
			byte[] buffer = new byte[resourceAsStream.available()];
			resourceAsStream.read(buffer);
			return new String(buffer);
		} catch (IOException e) {
			throw new CowebRuntimeException(e);
		}

	}

	public Class<T> getTarget() {
		return this.target;
	}

	public T newInstance() {
		try {
			return this.target.newInstance();
		} catch (Exception e) {
			throw new CowebRuntimeException("Can't create new instance of "
					+ this.target.getCanonicalName(), e);
		}
	}

	public T newInstance(final Object[] objects) {
		Class<?>[] paramTypes = ClassUtils.toClass(objects);
		Constructor<T> constructor;
		try {
			constructor = this.getTarget().getConstructor(paramTypes);
			return constructor.newInstance(objects);
		} catch (Exception e) {
			throw new CowebRuntimeException("Can't create new instance of "
					+ this.target.getCanonicalName(), e);
		}
	}

	public String simpleName() {
		return this.getTarget().getSimpleName();
	}

}
